<script setup lang='ts'>
import { AessionInfo, RoleEnum } from '@/models/@types';
import { appRef } from '@/models/app.ref';
import { FormatDate, clipboardWriteText } from '@/utils/common.methods';
import { Message } from '@arco-design/web-vue';
import { onMounted, onUnmounted, ref, watch } from 'vue';
import Explanation from '@/components/Explanation.vue'
import { GeneratePromptReq, promptService } from '@/services/prompt.service';
import Markdown from '../Markdown.vue';

/** 
 * 说明，公共会话组件 API 如下
 * -- props --
 * sessions     会话列表  AessionInfo[]
 * isSend       发送中
 * isrefresh    是否显示重新获取会话按钮
 * isGoodIdea   是否显示 Good Idea 按钮
 * chunk        流数据显示，仅在 isSend 为 true 时有效，isSend 结束后，需将该条消息写入  sessions 中
 * 
 * -- emits --
 * send         发送   Parma： value:string   会话框中的文本内容
 * remove       删除   Parma： value:string   回答/问题 的 uid
 * refresh      重载   Parma： value:string   该回答的 quote 
 * 
 * -- slots --
 * select-model 选择模型插槽
 * stop-send    停止响应
 */
const props = withDefaults(defineProps<{ sessions: AessionInfo[], isSend?: boolean, isGoodIdea?: boolean, isrefresh?: boolean, chunk?: string }>(), {
  sessions: [] as any
});
const emits = defineEmits(['send', 'remove', 'refresh']);
// slots = ['select-model']







const avatar = ref([appRef.user.data.avatar, appRef.user.ai.avatar])
const textarea = ref('');

watch(() => [props.isSend, props.sessions, props.chunk], () => {
  if (!props.isSend) {
    setPrompt();
  }
  scrollTopBottom()
});

const chunkData = ref('');
watch(() => props.chunk, (newData) => {
  chunkData.value = newData;
});

onMounted(() => {
  scrollTopBottom();
  setPrompt();
});


function onSend(): void {
  if (!props.isSend && textarea.value) {
    emits('send', textarea.value);
    prompts.value = [];
    chunkData.value = '';
    textarea.value = '';
  }
}

const sessionBox = ref(null)
function scrollTopBottom() {
  setTimeout(() => {
    if (!sessionBox.value) return;
    const { scrollHeight, clientHeight } = sessionBox.value;
    sessionBox.value.scrollTop = scrollHeight - clientHeight;
  }, 10);
}

function onCopy(richtext: string): void {
  clipboardWriteText(richtext).then(() => {
    Message.success('复制成功')
  })
}

/** 一个好点子 */
function onGoodIdea(): void {
  textarea.value = '这里应该是一个随机的好点子'
}

function onPrompt(text: string): void {
  textarea.value = text;
  onSend();
}
const prompts = ref([] as string[]);
let maxLen = 3;
function setPrompt(): void {
  prompts.value = [];
  const list: GeneratePromptReq[] = props.sessions?.map(val => { return { role: val.role, content: val.richtext } })
  const delayed = (list: string[], i: number = 0) => {
    if (i < list?.length) {
      if (list[i]) prompts.value.push(list[i]);
      if (prompts.value?.length > maxLen) {
        prompts.value.shift()
      }
      scrollTopBottom();
      setTimeout(() => {
        delayed(list, ++i)
      }, Math.random() * 200)
    }
  }
  promptService.generate_prompt(list).then(res => {
    const list = res.split('\n');
    delayed(list)
  })
}

</script>
<template>
  <div class="interactive flex-c">
    <div class="content flex-c" ref="sessionBox">
      <div class="sessions">
        <Explanation v-if="!sessions?.length"></Explanation>
        <div class="item flex-c" v-for="item in sessions" :key="item.uid"
          :style="{ 'align-items': item.role === RoleEnum.User ? 'flex-end' : 'flex-start' }">
          <div class="top flex" v-if="item.role === RoleEnum.User">
            <a-popconfirm content="确认删除该记录吗?" type="error" @ok="emits('remove', item.uid)">
              <icon-delete class="icon" />
            </a-popconfirm>
            <icon-copy class="icon" @click="onCopy(item.richtext)" />
            <span class="date">{{ FormatDate(item.timestamp) }} </span>
            <!-- <img class="avatar" :src="avatar[0]" alt=""> -->
            <img class="avatar" src="@/assets/images/user_avatar.png" alt="">
          </div>
          <div class="top flex" v-else>
            <!-- <img class="avatar" :src="avatar[1]" alt=""> -->
            <img class="avatar" src="@/assets/images/ai_avatar.png" alt="">
            <span class="date">{{ FormatDate(item.timestamp) }} </span>
            <a-popconfirm content="确认删除该记录吗?" type="error" @ok="emits('remove', item.uid)">
              <icon-delete class="icon" />
            </a-popconfirm>
            <icon-copy class="icon" @click="onCopy(item.richtext)" />
            <icon-refresh class="icon" @click="emits('refresh', item.quote)" v-if="isrefresh" />
          </div>
          <Markdown class="richtext" v-if="item.role === RoleEnum.User" :source="item.richtext" previewTheme="cyanosis" />
          <!-- <div class="richtext" style="padding: 10px 20px;" v-if="item.role === RoleEnum.User" v-html="item.richtext">
          </div> -->
          <Markdown class="richtext ai-richtext" v-else :source="item.richtext" :reverse="true" />
          <!-- <div class="richtext" :class="{ 'ai-richtext': item.role === RoleEnum.AI }"
            v-html="hljs.highlightAuto(md.render(item.richtext)).value"> </div> -->
        </div>
        <div class="item flex-c" :style="{ 'align-items': 'flex-start' }" v-if="isSend">
          <div class="top flex">
            <img class="avatar" src="@/assets/images/ai_avatar.png" alt="">
            <span class="date">{{ FormatDate(Date.now()) }} </span>
          </div>
          <Markdown class="richtext ai-richtext" :reverse="true" :source="chunkData || '请稍后，数据请求中......'" />
        </div>
      </div>
      <div class="prompt flex">
        <div class="left flex">
          <a-button class="item" v-if="isGoodIdea" type="outline" @click="onGoodIdea" :loading="isSend">Good
            Idea</a-button>
          <div class="item flex">
            <slot name="select-model"></slot>
            <slot name="stop-send"></slot>
          </div>
        </div>
        <div class="right flex-c">
          <a-button class="item " type="primary" :disabled="isSend" v-for="item in prompts" @click="onPrompt(item)"
            :key="item">
            {{ item }}
          </a-button>
        </div>
      </div>
    </div>


    <div class="bottom flex">
      <a-textarea class="textarea" v-model="textarea" :auto-size="{ minRows: 2, maxRows: 7 }"
        placeholder="粘贴或输入你的需求，如: 请帮我看看文章有没有问题，附上文章的内容 （Ctrl + Enter = 发送，Enter = 换行）" @keydown.ctrl.enter="onSend" />
      <a-button class="send" type="primary" :disabled="!textarea" @click.stop="onSend" :loading="isSend">
        <template #icon> <icon-send /> </template>
        <template #default>发送</template>
      </a-button>
    </div>
  </div>
</template>
<style lang='scss' scoped>
.interactive {
  height: 100%;
  width: 100%;
  max-width: 1270px;

  &>* {
    width: 100%;
  }

  .content {
    flex: 1;
    overflow-y: auto;
    margin-top: 10px;
    padding: 10px;
    scroll-behavior: smooth;
    justify-content: space-between;

    .sessions {
      width: 100%;
      flex: 1;

      .item {
        margin-bottom: 10px;
        width: 100%;

        .top {
          .date {
            margin: 0 10px;
            font-size: 12px;
            color: var(--color-neutral-6);
          }

          .icon {
            cursor: pointer;
            margin: 0 5px;
            font-size: 15px;
          }

          .avatar {
            width: 30px;
            height: 30px;
            border-radius: 50%;
          }
        }

        .richtext {
          width: auto;
          max-width: calc(100% - 80px);
          margin: 5px 40px;
          border-radius: 3px;
          line-height: 23px;
          word-break: break-all;
          background: rgb(var(--green-3));
          color: var(--color-neutral-10);
          border-radius: 3px;

          ::v-deep p {
            margin: 0;
          }
        }

        .ai-richtext {
          background: var(--color-neutral-10);
          color: var(--color-neutral-4);
        }
      }
    }




    .prompt {
      width: 100%;
      margin: 30px 0 5px;
      justify-content: space-between;
      align-items: flex-end;

      .left {
        .item {
          margin: 0;
          margin-right: 5px;

          &:last-child {
            margin: 0;
          }
        }
      }

      .right {
        max-width: 50%;
        overflow: hidden;
        align-items: flex-end;

        .item {
          width: fit-content;
          max-width: 100%;
          border-radius: 20px 20px 0 20px;
          min-height: 37px;
          height: auto;
          margin-bottom: 10px;
          cursor: pointer;
          white-space: pre-line;
          text-align: left;
          padding: 10px 20px;
        }
      }

      @media screen and (max-width: 1200px) {
        flex-direction: column;

        .right {
          width: inherit;
          max-width: max-content;
          flex-direction: revert;
          overflow-x: auto;
          margin-top: 10px;

          .item {
            max-width: max-content;
            height: 0px;
            min-height: 25px;
            margin-right: 10px;
            border-radius: 5px;
            font-size: .8rem;
            white-space: nowrap;
            text-align: left;
            padding: 0 10px;
          }
        }
      }
    }
  }

  .bottom {
    position: relative;
    align-items: flex-end;
    padding-bottom: 17px;

    .textarea {
      padding-right: 100px;
    }

    .send {
      position: absolute;
      right: 10px;
      bottom: 27px;
      // margin-left: 10px;
    }

    @media screen and (max-width: 1200px) {
      padding-bottom: 0;

      .send {
        position: absolute;
        right: 10px;
        bottom: 10px;
      }
    }
  }
}
</style>